package tse

import (
	"gitee.com/amoyx/cloud-provider/pkg/cloud/tencent/models"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
	"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
	qtse "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tse/v20201207"
)

type EurekaGreeter interface {
	Eureka(region string) EurekaInterface
}

type EurekaInterface interface {
	CreateInstance(args models.EurekaRequest) (result models.CreateResponseParams, err error)
	Get(id string) (result models.TseBaseResponse, err error)
	ListByName(name string) (list []models.TseBaseResponse, err error)
	ListAll() (list []models.TseBaseResponse, err error)
	DeleteInstance(id string) (err error)
	EnableWanAddr(id string) (err error)
	DisableWanAddr(id string) (err error)
	QueryInstanceAccessAddress(id string) (result models.InstanceAccessAddress, err error)
}

type eureka struct {
	tse    *TSE
	region string
	client *qtse.Client
}

func newEureka(tse *TSE, region string) EurekaInterface {
	v := &eureka{
		tse:    tse,
		region: region,
	}
	cpf := profile.NewClientProfile()
	cpf.HttpProfile.Endpoint = string(TseEndPoint)
	client, _ := qtse.NewClient(v.tse.Credential(), v.region, cpf)
	v.client = client
	return v
}

func (e *eureka) CreateInstance(args models.EurekaRequest) (result models.CreateResponseParams, err error) {
	request := qtse.NewCreateEngineRequest()
	request.EngineType = common.StringPtr("eureka")
	request.EngineVersion = common.StringPtr(args.EngineVersion)
	request.EngineResourceSpec = common.StringPtr(args.GoodsSpec)
	request.EngineRegion = common.StringPtr(e.region)
	if args.EngineNodeNum < 3 {
		args.EngineNodeNum = 3
	}
	request.EngineProductVersion = common.StringPtr("STANDARD")
	request.EngineNodeNum = common.Int64Ptr(args.EngineNodeNum)
	request.VpcId = common.StringPtr(args.VpcId)
	request.SubnetId = common.StringPtr(args.SubnetId)
	request.EngineName = common.StringPtr(args.EngineName)
	request.TradeType = common.Int64Ptr(0)
	request.PrepaidPeriod = common.Int64Ptr(1)
	request.PrepaidRenewFlag = common.Int64Ptr(1)
	response, err := e.client.CreateEngine(request)
	if err != nil {
		return
	}
	res := response.Response
	result.RequestId = *res.RequestId
	result.InstanceSet = append(result.InstanceSet, *res.InstanceId)
	return
}

func (e *eureka) QueryInstanceAccessAddress(id string) (result models.InstanceAccessAddress, err error) {
	request := qtse.NewDescribeSREInstanceAccessAddressRequest()
	request.InstanceId = common.StringPtr(id)
	response, err := e.client.DescribeSREInstanceAccessAddress(request)
	if err != nil {
		return
	}
	res := response.Response
	result.ConsoleInternetAddress = *res.ConsoleInternetAddress
	result.ConsoleIntranetAddress = *res.ConsoleIntranetAddress
	result.InternetAddress = *res.InternetAddress
	result.IntranetAddress = *res.IntranetAddress
	result.ConsoleInternetBandWidth = *res.ConsoleInternetBandWidth
	result.InternetBandWidth = *res.InternetBandWidth
	result.RequestId = *res.RequestId
	return
}

func (e *eureka) Get(id string) (result models.TseBaseResponse, err error) {
	list, err := e.query(map[string]string{"InstanceId": id})
	if len(list) > 0 {
		result = list[0]
	}
	return
}

func (e *eureka) ListByName(name string) (list []models.TseBaseResponse, err error) {
	return e.query(map[string]string{"Name": name})
}

func (e *eureka) ListAll() (list []models.TseBaseResponse, err error) {
	return e.query(map[string]string{})
}

// DeleteInstance 删除nacos实例
func (e *eureka) DeleteInstance(id string) (err error) {
	request := qtse.NewDeleteEngineRequest()
	request.InstanceId = common.StringPtr(id)
	_, err = e.client.DeleteEngine(request)
	return
}

// EnableWanAddr 开启公网访问
func (e *eureka) EnableWanAddr(id string) (err error) {
	request := qtse.NewUpdateEngineInternetAccessRequest()
	request.InstanceId = common.StringPtr(id)
	request.EnableClientInternetAccess = common.BoolPtr(true)
	request.EngineType = common.StringPtr("nacos")
	_, err = e.client.UpdateEngineInternetAccess(request)
	return
}

// DisableWanAddr 关闭公网访问
func (e *eureka) DisableWanAddr(id string) (err error) {
	request := qtse.NewUpdateEngineInternetAccessRequest()
	request.InstanceId = common.StringPtr(id)
	request.EnableClientInternetAccess = common.BoolPtr(false)
	request.EngineType = common.StringPtr("nacos")
	_, err = e.client.UpdateEngineInternetAccess(request)
	return
}

func (e *eureka) query(args map[string]string) (list []models.TseBaseResponse, err error) {
	request := qtse.NewDescribeSREInstancesRequest()
	var filters []*qtse.Filter
	for key, val := range args {
		filters = append(filters, &qtse.Filter{
			Name:   common.StringPtr(key),
			Values: common.StringPtrs([]string{val}),
		})
	}
	request.QueryType = common.StringPtr("eureka")
	response, err := e.client.DescribeSREInstances(request)

	if err != nil {
		return
	}
	for _, row := range response.Response.Content {
		addrInfo, _ := e.QueryInstanceAccessAddress(*row.InstanceId)
		var subnetId string
		if len(row.SubnetIds) > 0 {
			subnetId = *row.SubnetIds[0]
		}
		list = append(list, models.TseBaseResponse{
			InstanceId:            *row.InstanceId,
			Name:                  *row.Name,
			EngineVesion:          *row.Edition,
			Status:                *row.Status,
			SpecId:                *row.SpecId,
			Replica:               *row.Replica,
			EngineType:            *row.Type,
			VpcId:                 *row.VpcId,
			Paymode:               *row.Paymode,
			CreateTime:            *row.CreateTime,
			EngineRegion:          *row.EngineRegion,
			EnableInternet:        *row.EnableInternet,
			EnableConsoleInternet: *row.EnableConsoleInternet,
			EnableConsoleIntranet: *row.EnableConsoleIntranet,
			ConfigInfoVisible:     *row.ConfigInfoVisible,
			ConsoleDefaultPwd:     *row.ConsoleDefaultPwd,
			TradeType:             *row.TradeType,
			AutoRenewFlag:         *row.AutoRenewFlag,
			CurDeadline:           *row.CurDeadline,
			IsolateTime:           *row.IsolateTime,
			ProductVersion:        *row.FeatureVersion,
			EnableClientIntranet:  *row.EnableClientIntranet,
			SubnetId:              subnetId,
			InstanceAccessAddress: addrInfo,
		})

	}
	return
}
